﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace ExchangeListener
{
	class RecurringAppointmentListener
	{
		private RecurringAppointmentListener()
		{

		}

		private static RecurringAppointmentListener gra;

		public static RecurringAppointmentListener Instance
		{
			get
			{
				if (gra == null)
					gra = new RecurringAppointmentListener();
				return gra;
			}
		}

		private Hashtable list;

		private DateTime StartTime;

		public void Listener(DateTime _StartTime, DateTime EndTime, ExchangeServiceBinding esb, Hashtable _list)
		{
			list = _list;
			StartTime = _StartTime;
			GetAppointments(StartTime, EndTime, esb);
		}



		private void GetAppointments(DateTime StartTime, DateTime EndTime, ExchangeServiceBinding esb)
		{
			//restrict the returned items to just items of a specific message class
			PathToUnindexedFieldType MsgClassField = new PathToUnindexedFieldType();
			MsgClassField.FieldURI = UnindexedFieldURIType.calendarIsRecurring;
			ConstantValueType MsgClassToGet = new ConstantValueType();
			MsgClassToGet.Value = "1";
			FieldURIOrConstantType MsgClassConstant = new FieldURIOrConstantType();
			MsgClassConstant.Item = MsgClassToGet;
			IsEqualToType iett = new IsEqualToType();
			iett.FieldURIOrConstant = MsgClassConstant;
			iett.Item = MsgClassField;

			var response = esb.FindItem(new FindItemType
			{
				ItemShape = new ItemResponseShapeType
				{
					BaseShape = DefaultShapeNamesType.AllProperties,
					AdditionalProperties = new PathToUnindexedFieldType[] { 
						new PathToUnindexedFieldType{
						FieldURI=UnindexedFieldURIType.calendarIsMeeting
						}
					}
				},
				ParentFolderIds = new DistinguishedFolderIdType[] 
						{ 
							new DistinguishedFolderIdType { Id = DistinguishedFolderIdNameType.calendar }, 
						},

				Restriction = new RestrictionType { Item = iett }
			});

			var items = ((ArrayOfRealItemsType)((FindItemResponseMessageType)response.ResponseMessages.Items[0]).RootFolder.Item).Items;

			if (items != null)
				foreach (CalendarItemType ci in items)
				{
					if (ci.ReminderIsSet)
					{
						var item = esb.GetItem(new GetItemType
						{
							ItemIds = new BaseItemIdType[] { ci.ItemId },
							ItemShape = new ItemResponseShapeType { BaseShape = DefaultShapeNamesType.AllProperties },
						});

						var cal = ((CalendarItemType)((ItemInfoResponseMessageType)(((BaseResponseMessageType)(item)).ResponseMessages.Items[0])).Items.Items[0]);
						if (cal.Recurrence != null)
						{
							Appointment ap = CalcAppointment(cal);
							if (ap != null)
								list.Add(ap.ID, ap);
						}
					}
				}
		}

		private int CalcRecurrenceRange(CalendarItemType cal)
		{
			RecurrenceRangeBaseType recurr = cal.Recurrence.Item1;

			if (recurr != null)
			{
				if (recurr is EndDateRecurrenceRangeType)
				{
					var rec = (EndDateRecurrenceRangeType)recurr;
					if (DateTime.Now > rec.EndDate.ToLocalTime())
						return -1;
					else
						return 0;
				}
				else if (recurr is NoEndRecurrenceRangeType)
				{
					return 0;
				}
				else if (recurr is NumberedRecurrenceRangeType)
				{
					var rec = (NumberedRecurrenceRangeType)recurr;
					return rec.NumberOfOccurrences;
				}
				else
					return -1;
			}
			else
				return -1;
		}

		private Appointment CalcAppointment(CalendarItemType cal)
		{
			int times = CalcRecurrenceRange(cal);
			if (times == -1)
				return null;

			Appointment ap = new Appointment();
			ap.ID = cal.ItemId.Id;
			ap.Subject = cal.Subject;
			ap.Location = cal.Location;
            ap.Start = cal.ReminderDueBy.ToLocalTime();
			ap.ReminderMinutesBeforeStart = Convert.ToInt32(cal.ReminderMinutesBeforeStart);
			ap.IsNotified = false;

            return ap;
        }

            //RecurrencePatternBaseType rpbt = cal.Recurrence.Item;
            //if (rpbt != null)
            //{
            //    if (rpbt is DailyRecurrencePatternType)
            //    {
            //        DailyRecurrencePatternType drpt = (DailyRecurrencePatternType)rpbt;
            //        return CalcDailyRecur(ap, drpt.Interval, times);
            //    }
            //    else if (rpbt is WeeklyRecurrencePatternType)
            //    {
            //        return null;
            //    }
            //    else if (rpbt is AbsoluteMonthlyRecurrencePatternType)
            //    {
            //        AbsoluteMonthlyRecurrencePatternType amrpt=(AbsoluteMonthlyRecurrencePatternType)rpbt;
            //        return CalcAbsoluteMonthlyRecur(ap,amrpt.Interval,times);
            //    }
            //    else if (rpbt is RelativeMonthlyRecurrencePatternType)
            //    {
            //        return null;
            //    }
            //    else if (rpbt is AbsoluteYearlyRecurrencePatternType)
            //    {
            //        AbsoluteYearlyRecurrencePatternType ayrpt = (AbsoluteYearlyRecurrencePatternType)rpbt;
            //        return CalcAbsoluteYearlyRecur(ap, 1, times);
            //    }
            //    else if (rpbt is RelativeYearlyRecurrencePatternType)
            //    {
            //        return null;
            //    }
            //    else
            //    {
            //        return null;
            //    }
            //}
            //else
		//}

		#region 计算

        //private Appointment CalcDailyRecur(Appointment ap, int Interval, int times)
        //{
        //    int count = 1;
        //    while (ap.Start < StartTime)
        //    {
        //        if (times > 0) //有次数限制
        //        {
        //            if (count < times)
        //            {
        //                ap.Start = ap.Start.AddDays(Interval);
        //                count++;
        //            }
        //            else if (count == times)
        //            {
        //                break;
        //            }
        //            else
        //            {
        //                return null;
        //            }
        //        }
        //        else //NoEnd与EndDate
        //        {
        //            ap.Start = ap.Start.AddDays(Interval);
        //        }
        //    }
        //    return ap;
        //}

        //private Appointment CalcAbsoluteMonthlyRecur(Appointment ap, int Interval, int times)
        //{
        //    int count = 1;
        //    int DayOfMonch = ap.Start.Day;
        //    while (ap.Start < StartTime)
        //    {
        //        if (times > 0) //有次数限制
        //        {
        //            if (count < times)
        //            {
        //                if (ap.Start.Day < DayOfMonch)
        //                {
        //                    ap.Start = ap.Start.AddMonths(Interval);
        //                    ap.Start = ap.Start.AddDays(DayOfMonch - ap.Start.Day);
        //                }
        //                else
        //                    ap.Start = ap.Start.AddMonths(Interval);

        //                count++;
        //            }
        //            else if (count == times)
        //            {
        //                break;
        //            }
        //            else
        //            {
        //                return null;
        //            }
        //        }
        //        else //NoEnd与EndDate
        //        {
        //            if (ap.Start.Day < DayOfMonch)
        //            {
        //                ap.Start = ap.Start.AddMonths(Interval);
        //                ap.Start = ap.Start.AddDays(DayOfMonch - ap.Start.Day);
        //            }
        //            else
        //                ap.Start = ap.Start.AddMonths(Interval);
        //        }
        //    }
        //    return ap;
        //}

        //private Appointment CalcAbsoluteYearlyRecur(Appointment ap, int Interval, int times)
        //{
        //    int count = 1;
        //    int dayofmonth = ap.Start.Day;
        //    int monthofyear = ap.Start.Month;
        //    while (ap.Start < StartTime)
        //    {
        //        if (times > 0) //有次数限制
        //        {
        //            if (count < times)
        //            {
        //                if (dayofmonth == 29 && monthofyear == 2)
        //                {
        //                    ap.Start = ap.Start.AddYears(Interval);
        //                    if (DateTime.IsLeapYear(ap.Start.Year))
        //                        ap.Start = ap.Start.AddDays(1);
        //                }
        //                else
        //                    ap.Start = ap.Start.AddYears(Interval);

        //                count++;
        //            }
        //            else if (count == times)
        //            {
        //                break;
        //            }
        //            else
        //            {
        //                return null;
        //            }
        //        }
        //        else //NoEnd与EndDate
        //        {
        //            if (dayofmonth == 29 && monthofyear == 2)
        //            {
        //                ap.Start = ap.Start.AddYears(Interval);
        //                if (DateTime.IsLeapYear(ap.Start.Year))
        //                    ap.Start = ap.Start.AddDays(1);
        //            }
        //            else
        //                ap.Start = ap.Start.AddYears(Interval);
        //        }
        //    }
        //    return ap;
        //}


		#endregion

        //private int MonthName2Num(string name)
        //{
        //    switch (name)
        //    {
        //            return 0
        //        default:
        //            break;
        //    }
        //}
	}
}
